﻿namespace LiteBlog.Controllers
{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Web.Mvc;
    using LiteBlog.Common;
    using LiteBlog.Models;
    using LiteBlog.Components;
    using LiteBlog.Controllers.Filters;
    using LiteBlog.Common.Entities;
    using System.Web.Script.Serialization;
    using LiteBlog.Common.Enums;
    using LiteBlog.Components.Contracts;
    using LiteBlog.Components.Enums;
    using LiteBlog.Controllers.Helpers;
    using LiteBlog.Common.Components;
    using LiteBlog.Controllers.Contracts;


    public class TagController : CompController<Tag, string>, ITagController
    {
        private IBlogComp _blogComp;
        private IPostComp _postComp;
        private IAuthorComp _authorComp;
        private ITagComp _tagComp;

        public IBlogComp BlogComponent
        {
            get
            {
                return _blogComp;
            }
        }

        public IPostComp PostComponent
        {
            get
            {
                return _postComp;
            }
        }

        public IAuthorComp AuthorComponent
        {
            get
            {
                return _authorComp;
            }
        }

        public ITagComp TagComponent { get { return _tagComp; } }

        public TagController(ITagComp tagComp, 
            IBlogComp blogComp, 
            IPostComp postComp, 
            IAuthorComp authorComp, 
            ISettingsComp settingsComp, 
            ICacheComp cacheComp)
            : base(tagComp, settingsComp, cacheComp)
        {
            _tagComp = tagComp;
            _blogComp = blogComp;
            _postComp = postComp;
            _authorComp = authorComp;
        }

        public override ActionResult Create(Tag model)
        {
            return base.Create(model);
        }

        public override ActionResult Update(string olid, Tag model)
        {
            return base.Update(olid, model);
        }

        public override ActionResult Delete(string id)
        {
            return base.Delete(id);
        }

        public override ActionResult Manage()
        {
            return base.Manage();
        }

        [TagNotFoundFilter(Order = 1)]
        [CrawlerFilterForPosts(Order = 2)]
        [PageExceptionFilter]
         public ActionResult Index(string id, int? page)
        {
            var postInfos = BlogComponent.GetPostsByTag(id);
            var postCollectionModel = new PostCollectionModel();

            var settings = GetSettings();
            int pageSize = settings.PostCount;
            page = page ?? 1;
            postCollectionModel.PageCount = postInfos.Count / pageSize + ((postInfos.Count % pageSize == 0) ? 0 : 1);
            page = Math.Min(page.Value, postCollectionModel.PageCount);
            int skip = (page.Value - 1) * pageSize;
            var posts = new List<Post>();
            foreach (var postInfo in postInfos.Skip(skip).Take(pageSize))
            {
                var post = PostComponent.Load(postInfo.FileID);
                DisplayHelper.SetDisplayTime(post);
                posts.Add(post);
            }
            postCollectionModel.PostCollection = posts;
            postCollectionModel.Page = page.Value;
            postCollectionModel.FilterId = id;
            postCollectionModel.FilterName = RouteData.Values["tagName"].ToString();
            postCollectionModel.UrlType = UrlType.Tag;
            // passing posts to CrawlerFilter
            RouteData.Values["posts"] = postCollectionModel;

            if (User.Identity.IsAuthenticated)
            {
                postCollectionModel.Author = AuthorComponent.Get(User.Identity.Name);
            }
            return View("Index", GetSiteLayout(), postCollectionModel);
        }

        [HttpGet]
        [AjaxExceptionFilter]
        public ActionResult GetMore(string id, int page)
        {
            var postInfos = BlogComponent.GetPostsByTag(id);
            var settings = GetSettings();
            int pageSize = settings.PostCount;
            int startIndex = page * pageSize;
            var posts = new List<Post>();
            foreach (var postInfo in postInfos.Skip(startIndex).Take(pageSize))
            {
                var post = PostComponent.Load(postInfo.FileID);
                DisplayHelper.SetDisplayTime(post);
                posts.Add(post);
            }
            var resultModel = new ResultModel();
            resultModel.Result = posts.Count > 0 ? true : false;
            var resultModelWithData = new ResultModelWithData<List<Post>>(resultModel, posts);
            return this.Json(resultModelWithData, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Widget()
        {
            var tags = TagComponent.Get();
            int min = 0;
            int maxTags = 30;
            if (tags.Any())
            {
                while (tags.Count(t => t.Count > min) > maxTags)
                    min++;
                int max = tags.Max(t => t.Count);
                int dev1 = (max - min) / 5;
                int dev2 = (max - min) * 3 / 5;
                int dev3 = (max - min) * 9 / 10;
                foreach (var tag in tags)
                {
                    if ((tag.Count > min) && (tag.Count <= (min + dev1)))
                        tag.Class = "small";
                    if ((tag.Count > (min + dev1)) && (tag.Count <= (min + dev2)))
                        tag.Class = "medium";
                    if ((tag.Count > (min + dev2)) && (tag.Count <= (min + dev3)))
                        tag.Class = "large";
                    if ((tag.Count > (min + dev3)) && (tag.Count <= max))
                        tag.Class = "larger";
                }
            }
            return PartialView(tags.Where(t => t.Count > min));
        }

        protected override string[] GetMessageParams(Tag model)
        {
            return new string[] { model.TagId, model.Name };
        }

        public override void ResolveComponents()
        {
            
        }
    }
}